package com.ibeeking.found.cop.b.rest.service.impl;

import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.google.gson.JsonObject;
import com.ibeeking.found.common.utils.UserUtils;
import com.ibeeking.found.cop.b.rest.service.*;
import com.ibeeking.found.cop.service.common.bo.MsgSendRuleBO;
import com.ibeeking.found.cop.service.common.constants.PublicParamConstant;
import com.ibeeking.found.cop.service.common.dos.*;
import com.ibeeking.found.cop.service.common.enums.*;
import com.ibeeking.found.cop.service.common.param.CopJobHandleParam;
import com.ibeeking.found.cop.service.common.param.MqSyncCopParam;
import com.ibeeking.found.cop.service.common.param.MsgMassMessageParam;
import com.ibeeking.found.cop.service.common.query.MsgMassMessagePageQuery;
import com.ibeeking.found.cop.service.common.query.MsgMassMessageQuery;
import com.ibeeking.found.cop.service.common.vo.CopAttachementVO;
import com.ibeeking.found.cop.service.common.vo.MsgMassMessageVO;
import com.ibeeking.found.cop.service.mapper.*;
import com.ibeeking.found.id.GenerateId;
import com.ibeeking.nematos.core.utils.SpringBeanUtil;
import com.ibeeking.nematos.exception.BusinessException;
import com.ibeeking.nematos.log.utils.LogUtils;
import com.ibeeking.nematos.utils.bean.BeanUtil;
import com.ibeeking.nematos.utils.cron.TaskScheduleModel;
import com.ibeeking.nematos.utils.data.Collections3;
import com.ibeeking.nematos.utils.date.DateUtil;
import com.ibeeking.nematos.utils.id.IdGenerator;
import com.ibeeking.nematos.utils.json.JsonUtils;
import me.chanjar.weixin.common.enums.WxType;
import me.chanjar.weixin.common.error.WxError;
import me.chanjar.weixin.cp.api.WxCpExternalContactService;
import me.chanjar.weixin.cp.api.WxCpService;
import me.chanjar.weixin.cp.api.impl.WxCpServiceImpl;
import me.chanjar.weixin.cp.bean.external.WxCpMsgTemplate;
import me.chanjar.weixin.cp.bean.external.WxCpMsgTemplateAddResult;
import me.chanjar.weixin.cp.bean.external.msg.Attachment;
import me.chanjar.weixin.cp.bean.external.msg.Text;
import me.chanjar.weixin.cp.config.WxCpConfigStorage;
import org.apache.commons.lang3.StringUtils;
import org.apache.http.Consts;
import org.apache.http.client.methods.CloseableHttpResponse;
import org.apache.http.client.methods.HttpPost;
import org.apache.http.entity.StringEntity;
import org.apache.http.impl.client.BasicResponseHandler;
import org.apache.http.impl.client.CloseableHttpClient;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import javax.annotation.Resource;
import java.io.IOException;
import java.time.LocalDateTime;
import java.util.ArrayList;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;

/**
 * @ClassName MsgMassMessageServiceImpl
 * @Description
 * @Author ibeeking
 * @Date 2021-01-27 18:50
 **/
@Service
public class MsgGroupMassMessageServiceImpl  extends ServiceImpl<MsgMassMessageMapper, MsgMassMessageDO> implements IMsgGroupMassMessageService {

    @Resource
    private MsgMassMessageMapper msgMassMessageMapper;

    @Resource
    private MsgMessageTaskMapper msgMessageTaskMapper;

    @Resource
    private ICopPublicParamService copPublicParamServiceImpl;

    @Resource
    private GroupMapper groupMapper;

    @Resource
    private GroupFriendsMapper groupFriendsMapper;

    @Resource
    private CopEmployeeMapper copEmployeeMapper;

    @Resource
    private GroupTagsRelMapper groupTagsRelMapper;

    @Resource
    private CopAttachementMapper copAttachementMapper;

    @Resource
    private ICopAttachementService copAttachementServiceImpl;

    @Resource
    private ICopJobCreateService copJobCreateServiceImpl;

    @Resource
    private IMqService mqServiceImpl;

    @Resource
    private IWxOpenService wxOpenServiceImpl;

    @Override
    public List<MsgMassMessageVO> list(MsgMassMessageQuery query) {
        List<MsgMassMessageDO> entityDOS = msgMassMessageMapper.selectList(new LambdaQueryWrapper<MsgMassMessageDO>()
                .eq(query.getId() != null, MsgMassMessageDO::getId, query.getId())
                .eq(MsgMassMessageDO::getChatType, WxCpMessageTypeEnum.MESSAGE_CHAT_TYPE_GROUP.getCode())
                .like(StringUtils.isNotBlank(query.getName()), MsgMassMessageDO::getName, query.getName())
                .eq(query.getStatus() != null, MsgMassMessageDO::getSendStatus, query.getStatus())
                .orderByDesc(MsgMassMessageDO::getCreateTime)
        );
        List<MsgMassMessageVO> entityVOS =JsonUtils.jsonToList(entityDOS, MsgMassMessageVO.class);
        entityVOS.forEach(x -> {
            String sendRuleStr = x.getSendRule();
            if(StringUtils.isNotEmpty(sendRuleStr)){
                MsgSendRuleBO msgSendRuleBO = JsonUtils.fromJson(sendRuleStr, MsgSendRuleBO.class);
                x.setMsgSendRule(msgSendRuleBO);
            }else{
                MsgSendRuleBO msgSendRuleBO = new MsgSendRuleBO();
                x.setMsgSendRule(msgSendRuleBO);
            }
            x.setSendStatusDesc(WxCpMessageAssignStatusEnum.getDescByCode(x.getSendStatus()));
        });
        return entityVOS;
    }

    @Override
    public Page<MsgMassMessageVO> pageList(MsgMassMessagePageQuery pageQuery) {
        LambdaQueryWrapper<MsgMassMessageDO> wrapper = new LambdaQueryWrapper<>();
        wrapper.eq(pageQuery.getId() != null, MsgMassMessageDO::getId, pageQuery.getId())
                .eq(MsgMassMessageDO::getChatType, WxCpMessageTypeEnum.MESSAGE_CHAT_TYPE_GROUP.getCode())
                .like(StringUtils.isNotBlank(pageQuery.getName()), MsgMassMessageDO::getName, pageQuery.getName())
                .eq(pageQuery.getStatus() != null, MsgMassMessageDO::getSendStatus, pageQuery.getStatus())
                .orderByDesc(MsgMassMessageDO::getCreateTime);
        Page<MsgMassMessageDO> entityDOPages = msgMassMessageMapper.selectPage(new Page<MsgMassMessageDO>(pageQuery.getPageNum(), pageQuery.getPageSize()), wrapper);
        Page<MsgMassMessageVO> entityVOPages = BeanUtil.convertPage(entityDOPages, MsgMassMessageVO.class);
        entityVOPages.getRecords().forEach(f ->{
            String sendRuleStr = f.getSendRule();
            if(StringUtils.isNotEmpty(sendRuleStr)){
                MsgSendRuleBO msgSendRuleBO = JsonUtils.fromJson(sendRuleStr, MsgSendRuleBO.class);
                f.setMsgSendRule(msgSendRuleBO);
            }else{
                MsgSendRuleBO msgSendRuleBO = new MsgSendRuleBO();
                f.setMsgSendRule(msgSendRuleBO);
            }
            f.setSendStatusDesc(WxCpMessageAssignStatusEnum.getDescByCode(f.getSendStatus()));
        });
        return entityVOPages;
    }

    @Transactional(rollbackFor = Exception.class)
    @Override
    public Boolean add(MsgMassMessageParam param) {
        String tenantId = UserUtils.getTenantId();
        checkUnique(param);
        MsgMassMessageDO entityDO = BeanUtil.convertBean(param, MsgMassMessageDO.class);
        Long msgId = GenerateId.generateId();
        entityDO.setId(msgId);
        entityDO.setChatType(WxCpMessageTypeEnum.MESSAGE_CHAT_TYPE_GROUP.getCode());
        entityDO.setCreateBy(UserUtils.getUserId());
        entityDO.setCreateTime(LocalDateTime.now());
        entityDO.setModifyTime(LocalDateTime.now());
        MsgSendRuleBO msgSendRuleBO = param.getMsgSendRule();
        if(msgSendRuleBO != null){
            entityDO.setSendRule(JsonUtils.toJsonStr(msgSendRuleBO));
        }
        Integer sendWay = param.getSendWay();
        if(sendWay == WxCpMessageSendWayEnum.MESSAGE_SEND_WAY_TASK.getCode()){
            String sendTimeStr = param.getSendTime();
            if(StringUtils.isEmpty(sendTimeStr)) throw new BusinessException("选择定时发送时候，必须设置任务时间！");
            LocalDateTime sendTime = DateUtil.strToLocalDateTime(sendTimeStr);
            if(sendTime!=null){
                entityDO.setSendTime(sendTime);
            }
        }
        msgMassMessageMapper.insert(entityDO);
        return true;
    }

    @Transactional(rollbackFor = Exception.class)
    @Override
    public Boolean modify(MsgMassMessageParam param) {
        String tenantId = UserUtils.getTenantId();
        MsgMassMessageDO entityDO = BeanUtil.convertBean(param, MsgMassMessageDO.class);
        Long msgId = entityDO.getId();
        entityDO.setChatType(WxCpMessageTypeEnum.MESSAGE_CHAT_TYPE_GROUP.getCode());
        entityDO.setModifyBy(UserUtils.getUserId());
        entityDO.setModifyTime(LocalDateTime.now());
        MsgSendRuleBO msgSendRuleBO = param.getMsgSendRule();
        if(msgSendRuleBO != null){
            entityDO.setSendRule(JsonUtils.toJsonStr(msgSendRuleBO));
        }
        Integer sendWay = param.getSendWay();
        if(sendWay == WxCpMessageSendWayEnum.MESSAGE_SEND_WAY_TASK.getCode()){
            String sendTimeStr = param.getSendTime();
            if(StringUtils.isEmpty(sendTimeStr)) throw new BusinessException("选择定时发送时候，必须设置任务时间！");
            LocalDateTime sendTime = DateUtil.strToLocalDateTime(sendTimeStr);
            if(sendTime!=null){
                entityDO.setSendTime(sendTime);
            }
        }
        msgMassMessageMapper.updateById(entityDO);

        return true;
    }

    @Transactional(rollbackFor = Exception.class)
    @Override
    public Boolean updateBatch(List<MsgMassMessageDO> entityDOList) {
        return super.updateBatchById(entityDOList);
    }

    @Transactional(rollbackFor = Exception.class)
    @Override
    public Integer summaryReceiverTotal(MsgSendRuleBO msgSendRuleBO){
        Integer totalCount = 0;
        if(msgSendRuleBO == null) return 0;

        Integer isAllGroup = msgSendRuleBO.getIsAllGroup();
        if(isAllGroup == 1){
            Integer groupFriendsCount = groupFriendsMapper.selectCount(new LambdaQueryWrapper<GroupFriendsDO>());
            totalCount = groupFriendsCount !=null?totalCount + groupFriendsCount:totalCount + 0;
        }else{
            List<String> groupOwnerIdList = msgSendRuleBO.getGroupOwnerCodeList();
            if(Collections3.isNotEmpty(groupOwnerIdList)) {
                List<GroupDO> groupDOS = groupMapper.selectList(new LambdaQueryWrapper<GroupDO>().in(GroupDO::getOwnerCode, groupOwnerIdList));
                List<Long> groupIds = Collections3.isNotEmpty(groupDOS)?groupDOS.stream().map(GroupDO::getId).collect(Collectors.toList()):null;
                if(Collections3.isNotEmpty(groupIds)) {
                    Integer groupFriendsCount = groupFriendsMapper.selectCount(new LambdaQueryWrapper<GroupFriendsDO>().in(GroupFriendsDO::getGroupId, groupIds));
                    totalCount = groupFriendsCount !=null?totalCount + groupFriendsCount:totalCount + 0;
                }
            }
            List<Long> groupTagsList = msgSendRuleBO.getGroupTagsList();
            if(Collections3.isNotEmpty(groupTagsList)) {
                List<GroupTagsRelDO> groupTagsRelDOList = groupTagsRelMapper.selectList(new LambdaQueryWrapper<GroupTagsRelDO>().in(GroupTagsRelDO::getTagsId,groupTagsList));
                if(Collections3.isNotEmpty(groupTagsRelDOList)) {
                    List<Long> groupIdList = groupTagsRelDOList.stream().map(GroupTagsRelDO::getGroupId).collect(Collectors.toList());
                    List<Long> groupIds = groupIdList.stream().distinct().collect(Collectors.toList());
                    Integer groupFriendsCount = groupFriendsMapper.selectCount(new LambdaQueryWrapper<GroupFriendsDO>().in(GroupFriendsDO::getGroupId, groupIds));
                    totalCount = groupFriendsCount !=null?totalCount + groupFriendsCount:totalCount + 0;
                }
            }
        }
        return totalCount;
    }

    @Override
    public Boolean copy(Long id) {
        MsgMassMessageDO entityDO = msgMassMessageMapper.selectById(id);
        if(entityDO == null) throw new BusinessException("没有查到相关记录！");
        Long newId = IdGenerator.getId();
        entityDO.setId(newId);
        entityDO.setCreateTime(LocalDateTime.now());
        entityDO.setModifyTime(LocalDateTime.now());
        entityDO.setSendCycle(0);
        if(entityDO.getSendWay() == 1){
            entityDO.setSendTime(null);
        }
        entityDO.setRtnMsgId(null);
        entityDO.setSendStatus(WxCpMessageAssignStatusEnum.MESSAGE_ASSIGN_STATUS_NOASSIGN.getCode());
        entityDO.setBuidTime(null);
        List<CopAttachementDO> copAttachementDOList = copAttachementMapper.selectList(new LambdaQueryWrapper<CopAttachementDO>().eq(CopAttachementDO::getMessageId,id));
        if(Collections3.isNotEmpty(copAttachementDOList)){
            copAttachementDOList.parallelStream().forEach(d->{
                d.setMessageId(newId);
                d.setId(IdGenerator.getId());
                d.setCreateTime(LocalDateTime.now());
                d.setModifyTime(LocalDateTime.now());
            });
            copAttachementMapper.insertBatchSomeColumn(copAttachementDOList);
        }
        msgMassMessageMapper.insert(entityDO);
        return true;
    }

    @Transactional(rollbackFor = Exception.class)
    @Override
    public Boolean sendWxCpGroupMassMessage(Long id) {
        String tenantId = UserUtils.getTenantId();
        MsgMassMessageDO entityDO = msgMassMessageMapper.selectById(id);
        if(entityDO == null) throw new BusinessException("没有查到相关记录！");
        Long msgId = entityDO.getId();
        Integer sendWay = entityDO.getSendWay();
        if(sendWay == 2){
            LocalDateTime sendTime = entityDO.getSendTime();
            if(sendTime.isBefore(LocalDateTime.now())) throw new BusinessException("已经过了定时发送时间，请重新设置定时发送时间！");
            if(sendTime != null) {
                TaskScheduleModel scheduleModel = new TaskScheduleModel();
                scheduleModel.setJobType(6);
                scheduleModel.setSecond(sendTime.getSecond());
                scheduleModel.setMinute(sendTime.getMinute());
                scheduleModel.setDay(sendTime.getDayOfMonth());
                scheduleModel.setMonth(sendTime.getMonthValue());
                scheduleModel.setFromYear(sendTime.getYear());
                scheduleModel.setToYear(sendTime.getYear());
                CopJobHandleParam handleParam = new CopJobHandleParam();
                handleParam.setId(msgId);
                handleParam.setTenantId(Integer.valueOf(tenantId));
                copJobCreateServiceImpl.createJobInfoForSendGroupMassMessage(Integer.valueOf(tenantId), scheduleModel, handleParam);
            }
        }else{
            this.getBean().sendGroupMassMessageToWxCp(Integer.valueOf(tenantId), msgId);
        }
        return true;
    }

    @Transactional(rollbackFor = Exception.class)
    @Override
    public Boolean stopWxCpGroupMassMessage(Long id) {
        String tenantId = UserUtils.getTenantId();
        MqSyncCopParam mqParam = new MqSyncCopParam();
        mqParam.setOperType(MqSyncOperatorTypeEnum.COP_SYNC_STOP_GROUP_MASS_MESSAGE.getCode());
        mqParam.setTenantId(Long.valueOf(tenantId));
        mqParam.setId(id);
        mqServiceImpl.sendSyncToWxTaskMessage(mqParam);
        return true;
    }

    @Override
    public MsgMassMessageVO view(Long id) {
        MsgMassMessageDO entityDO = msgMassMessageMapper.selectById(id);
        if(entityDO == null) throw new BusinessException("没有查到相关记录！");
        MsgMassMessageVO entityVO = BeanUtil.convertBean(entityDO, MsgMassMessageVO.class);
        if(entityVO != null) {
            String sendRuleStr = entityVO.getSendRule();
            if(StringUtils.isNotEmpty(sendRuleStr)){
                MsgSendRuleBO msgSendRuleBO = JsonUtils.fromJson(sendRuleStr, MsgSendRuleBO.class);
                entityVO.setMsgSendRule(msgSendRuleBO);
            }else{
                MsgSendRuleBO msgSendRuleBO = new MsgSendRuleBO();
                entityVO.setMsgSendRule(msgSendRuleBO);
            }
            entityVO.setSendStatusDesc(WxCpMessageAssignStatusEnum.getDescByCode(entityDO.getSendStatus()));
        }
        return entityVO;
    }

    @Transactional(rollbackFor = Exception.class)
    @Override
    public Boolean changeStatus(Long id, Integer status) {
        MsgMassMessageDO entityDO = msgMassMessageMapper.selectById(id);
        if(entityDO == null) throw new BusinessException("没有查到相关记录！");
        entityDO.setSendStatus(status);
        entityDO.setModifyBy(UserUtils.getUserId());
        entityDO.setModifyTime(LocalDateTime.now());
        return msgMassMessageMapper.updateById(entityDO) > 0;
    }

    @Transactional(rollbackFor = Exception.class)
    @Override
    public Boolean del(Long id) {
        MsgMassMessageDO entityDO = msgMassMessageMapper.selectById(id);
        if(entityDO == null) throw new BusinessException("没有查到相关记录！");
        return msgMassMessageMapper.deleteById(id) > 0;
    }
    /**
     * 从企业微信同步q群信息
     *
     * @param
     */
    @Transactional(rollbackFor = Exception.class)
    @Override
    public Integer syncGroupMassMessageToWxCp(Integer tenantId, Long msgId){
        MqSyncCopParam mqParam = new MqSyncCopParam();
        mqParam.setOperType(MqSyncOperatorTypeEnum.COP_SYNC_SEND_GROUP_MASS_MESSAGE.getCode());
        mqParam.setTenantId(Long.valueOf(tenantId));
        mqParam.setId(msgId);
        mqServiceImpl.sendSyncToWxTaskMessage(mqParam);
        return 1;
    }

    @Transactional(rollbackFor = Exception.class)
    @Override
    public Boolean refreshWxCpGroupMassMessageSendRecord() {
        String tenantId = UserUtils.getTenantId();
        MqSyncCopParam mqParam = new MqSyncCopParam();
        mqParam.setOperType(MqSyncOperatorTypeEnum.COP_SYNC_MESSAGE_SENDED_RECORD.getCode());
        mqParam.setTenantId(Long.valueOf(tenantId));
        mqParam.setChatType(WxCpMessageTypeEnum.MESSAGE_CHAT_TYPE_GROUP.getCode());
        String beforeRefreshDate = copPublicParamServiceImpl.getParamValue(PublicParamConstant.MASS_MESSAGE_RECORD_LAST_REFRESH_DATE);
        LocalDateTime nowDate = LocalDateTime.now();
        if(StringUtils.isEmpty(beforeRefreshDate)){
            mqParam.setBeginDate(DateUtil.localDateTimeToStr(nowDate.minusDays(29)));
        }else{
            mqParam.setBeginDate(beforeRefreshDate);
        }
        mqParam.setEndDate(DateUtil.localDateTimeToStr(nowDate));
        mqServiceImpl.sendSyncToWxTaskMessage(mqParam);
        return true;
    }

    @Transactional(rollbackFor = Exception.class)
    @Override
    public Boolean sendGroupMassMessageToWxCp(Integer tenantId, Long msgId) {
        if(msgId == null) throw new BusinessException("发送任务获取消息参数msgId为空");
        MsgMassMessageDO messageDO = msgMassMessageMapper.selectById(msgId);
        if(messageDO == null) throw new BusinessException("通过msgId获得的消息数据为空!");
        int sendCycle = messageDO.getSendCycle();
        String sendRules = messageDO.getSendRule();
        List<MsgMessageTaskDO> AllMsgMessageTaskList = new ArrayList<>();
        Map<String, Long> sendOwnerIdMap = null;
        List<String> allSendUserList = new ArrayList<>();
        List<MsgMessageTaskSenderDO> allValidSenderDOList = new ArrayList<>();
        List<MsgMessageTaskFriendsDO> allValidFriendsDOList = new ArrayList<>();
        if(StringUtils.isNotEmpty(sendRules)){
            MsgSendRuleBO msgSendRuleBO = JsonUtils.fromJson(sendRules, MsgSendRuleBO.class);
            allSendUserList = collectAllNeedSendGroupsOwnerCode(tenantId, msgSendRuleBO);
        }
        if(Collections3.isNotEmpty(allSendUserList)){
            List<CopEmployeeDO> copEmployeeDOList = copEmployeeMapper.selectList(new LambdaQueryWrapper<CopEmployeeDO>().in(CopEmployeeDO::getEmployeeCode,allSendUserList));
            if(Collections3.isNotEmpty(copEmployeeDOList)){
                sendOwnerIdMap = copEmployeeDOList.stream().collect(Collectors.toMap(CopEmployeeDO::getEmployeeCode, CopEmployeeDO::getId, (o, n) -> n));
            }
        }
        allSendUserList.add("wrmiEENwAAeGq9dNlNFjHae2nvZnCxrw");

        WxCpService wxCpService = wxOpenServiceImpl.getWxCpService(tenantId.longValue());
        WxCpConfigStorage wxCpConfigStorage = wxCpService.getWxCpConfigStorage();
        if (wxCpConfigStorage == null) {
            throw new BusinessException("获取企微服务失败!");
        }
        LogUtils.info("====process wxCpConfigStorage:{}====", JsonUtils.toJsonStr(wxCpConfigStorage));

        WxCpExternalContactService wxCpExternalContactService = wxCpService.getExternalContactService();
        if (wxCpExternalContactService == null) throw new BusinessException("获取企微服务外部联系人服务!");

        WxCpMsgTemplate wxCpMsgTemplate = new WxCpMsgTemplate();
        wxCpMsgTemplate.setChatType(WxCpMessageTypeEnum.MESSAGE_CHAT_TYPE_GROUP.getCode());
        me.chanjar.weixin.cp.bean.external.msg.Text msgText = new Text();
        msgText.setContent(messageDO.getContent());
        wxCpMsgTemplate.setText(msgText);
        //添加附件
        CopAttachementVO copAttachementVO = copAttachementServiceImpl.queryByMessageId(msgId);
        if(null != copAttachementVO) {
            //先把消息中的附件同步到企微
            copAttachementServiceImpl.syncMessageAttachementsToWxCp(msgId);
            List<CopAttachementVO> copAttachementVOS = new ArrayList<>();
            copAttachementVOS.add(copAttachementVO);
            List<Attachment>  attachementList = copAttachementServiceImpl.transerCopAttachementToWxcpAttachement(copAttachementVOS);
            wxCpMsgTemplate.setAttachments(attachementList);
        }
        for(String ownerCode: allSendUserList) {
            MsgMessageTaskDO msgMessageTaskDO = new MsgMessageTaskDO();
            msgMessageTaskDO.setChatType(WxCpMessageTypeEnum.MESSAGE_CHAT_TYPE_GROUP.getCode());
            msgMessageTaskDO.setId(IdGenerator.getId());
            msgMessageTaskDO.setMessageId(messageDO.getId());
            msgMessageTaskDO.setSenderId(sendOwnerIdMap!=null?sendOwnerIdMap.get(ownerCode):null);
            msgMessageTaskDO.setSenderCode(ownerCode);
            msgMessageTaskDO.setSendWay(messageDO.getSendWay());
            if(messageDO.getSendWay() == WxCpMessageSendWayEnum.MESSAGE_SEND_WAY_TASK.getCode()){
                msgMessageTaskDO.setSendTime(messageDO.getSendTime());
            }else {
                msgMessageTaskDO.setSendTime(LocalDateTime.now());
                messageDO.setSendTime(LocalDateTime.now());
            }
            try {
                wxCpMsgTemplate.setSender(ownerCode);
                WxCpMsgTemplateAddResult wxCpMsgTemplateAddResult = wxCpExternalContactService.addMsgTemplate(wxCpMsgTemplate);
                LogUtils.info("====process wxCpMsgTemplateAddResult:{}====", JsonUtils.toJsonStr(wxCpMsgTemplateAddResult));
                if (Collections3.isNotEmpty(allSendUserList)) {
                    msgMessageTaskDO.setTotalFriendsList(JsonUtils.toJsonStr(allSendUserList));
                }
                if (wxCpMsgTemplateAddResult.getErrCode() == 0) {
                    String rtnMsgId = wxCpMsgTemplateAddResult.getMsgId();
                    List<String> failFriendsIdList = wxCpMsgTemplateAddResult.getFailList();
                    messageDO.setRtnMsgId(rtnMsgId);
                    messageDO.setSendStatus(WxCpMessageAssignStatusEnum.MESSAGE_ASSIGN_STATUS_ASSIGNED.getCode());
                    msgMessageTaskDO.setRtnMsgId(rtnMsgId);
                    HashSet<String> allSendUserHash = new HashSet<>(allSendUserList);
                    List<String> successFriendsIdHash = new ArrayList<>(allSendUserList);
                    if (Collections3.isNotEmpty(failFriendsIdList)) {
                        HashSet<String> failFriendsIdHash = new HashSet<>(failFriendsIdList);
                        allSendUserHash.removeAll(failFriendsIdHash);
                        successFriendsIdHash.clear();
                        successFriendsIdHash = new ArrayList<>(allSendUserHash);
                        msgMessageTaskDO.setInvalidFriendsList(JsonUtils.toJsonStr(failFriendsIdList));
                    }
                    if (Collections3.isNotEmpty(successFriendsIdHash)) {
                        msgMessageTaskDO.setValidFriendsList(JsonUtils.toJsonStr(successFriendsIdHash));
                        for (String friendsCode : successFriendsIdHash) {
                            MsgMessageTaskFriendsDO msgMessageTaskFriendsDO = new MsgMessageTaskFriendsDO();
                            msgMessageTaskFriendsDO.setId(IdGenerator.getId());
                            msgMessageTaskFriendsDO.setChatType(WxCpMessageTypeEnum.MESSAGE_CHAT_TYPE_GROUP.getCode());
                            msgMessageTaskFriendsDO.setMessageId(messageDO.getId());
                            msgMessageTaskFriendsDO.setTaskId(messageDO.getId());
                            msgMessageTaskFriendsDO.setMessageCode(rtnMsgId);
                            msgMessageTaskFriendsDO.setFriendsCode(friendsCode);
                            msgMessageTaskFriendsDO.setSendStatus(WxCpMessageTaskSendStatusEnum.MESSAGE_TASK_STATUS_NO_SEND.getCode());

                            allValidFriendsDOList.add(msgMessageTaskFriendsDO);
                        }
                    }
                } else {
                    messageDO.setSendStatus(WxCpMessageAssignStatusEnum.MESSAGE_ASSIGN_STATUS_ASSIGNED.getCode());
                    msgMessageTaskDO.setInvalidFriendsList(JsonUtils.toJsonStr(allSendUserList));
                }
            } catch (Exception e) {
                LogUtils.error("发送消息异常:{}", e);
                messageDO.setSendStatus(WxCpMessageAssignStatusEnum.MESSAGE_ASSIGN_STATUS_ASSIGNED.getCode());
                msgMessageTaskDO.setInvalidFriendsList(JsonUtils.toJsonStr(allSendUserList));
                msgMessageTaskDO.setRemark("发送消息失败!");
            }
            AllMsgMessageTaskList.add(msgMessageTaskDO);
        }
        if (messageDO != null) {
            messageDO.setSendCycle(sendCycle + 1);
            msgMassMessageMapper.updateById(messageDO);
        }
        if(Collections3.isNotEmpty(AllMsgMessageTaskList)){
            msgMessageTaskMapper.insertBatchSomeColumn(AllMsgMessageTaskList);
        }
        return true;
    }


    @Transactional(rollbackFor = Exception.class)
    @Override
    public Boolean stopSendGroupMassMessageToWxCp(Integer tenantId, Long msgId) {
        if(msgId == null) throw new BusinessException("发送任务获取消息参数msgId为空");
        MsgMassMessageDO messageDO = msgMassMessageMapper.selectById(msgId);
        if(messageDO == null) throw new BusinessException("通过msgId获得的消息数据为空!");
        String rtnMsgId = messageDO.getRtnMsgId();
        if(StringUtils.isNotEmpty(rtnMsgId)){
            Boolean result = askWxCpToStopSendMassMessage(tenantId.toString(), rtnMsgId);
            if(result){
                messageDO.setSendStatus(WxCpMessageAssignStatusEnum.MESSAGE_ASSIGN_STATUS_CANCEL.getCode());
                msgMassMessageMapper.updateById(messageDO);
            }
        }
        return true;
    }
    /**
     * 校验唯一性
     *
     * @param param
     */
    public void checkUnique(MsgMassMessageParam param) {
        if (param == null) {
            throw new BusinessException("当前记录不存在!");
        }
        //code name确保等级唯一性
        LambdaQueryWrapper<MsgMassMessageDO> queryWrapper = new LambdaQueryWrapper<MsgMassMessageDO>()
                .ne(param.getId() != null, MsgMassMessageDO::getId, param.getId())
                .eq(MsgMassMessageDO::getName, param.getName());
        List<MsgMassMessageDO> dos = msgMassMessageMapper.selectList(queryWrapper);
        if (Collections3.isNotEmpty(dos)) {
            throw new BusinessException("已经存在同名的记录!");
        }
    }

    /**
     * 基于消息的发送规则收集所有需要发送的客户或客户群Code清单
     *
     * @param msgSendRule
     */
    private List<String> collectAllNeedSendGroupsOwnerCode(Integer tenantId,MsgSendRuleBO msgSendRule){
        if(msgSendRule!=null){
            List<String> allReceiverCodes = new ArrayList<>();
            Integer allGroups = msgSendRule.getIsAllGroup();
            if(allGroups!=null && allGroups == 1){
                List<GroupDO> allGroupDOS = groupMapper.selectList(new LambdaQueryWrapper<GroupDO>().isNotNull(GroupDO::getOwnerCode));
                if(Collections3.isNotEmpty(allGroupDOS)) {
                    List<String> allGroupOwnerCodes = allGroupDOS.parallelStream().map(GroupDO::getOwnerCode).collect(Collectors.toList());
                    allReceiverCodes.addAll(allGroupOwnerCodes);
                }
            }
            List<String> selectedGroupOwnerCodes = msgSendRule.getGroupOwnerCodeList();
            if(Collections3.isNotEmpty(selectedGroupOwnerCodes)){
                allReceiverCodes.addAll(selectedGroupOwnerCodes);
            }
            List<Long> selectedGroupTags = msgSendRule.getGroupTagsList();
            if(Collections3.isNotEmpty(selectedGroupTags)){
                List<String> groupOwnerCodeList = groupTagsRelMapper.getGroupOwnerCodeListByTagsIdsList(tenantId, selectedGroupTags);
                allReceiverCodes.addAll(groupOwnerCodeList);
            }
            return allReceiverCodes;
        }
        return null;
    }


    private Boolean askWxCpToStopSendMassMessage(String tenantId, String msgId){
        try {
            String getFollowUserUrl = "/cgi-bin/externalcontact/cancel_groupmsg_send?access_token=%s";
            WxCpServiceImpl wxCpService = (WxCpServiceImpl)wxOpenServiceImpl.getWxCpService(Long.valueOf(tenantId));
            WxCpConfigStorage wxCpConfigStorage = wxCpService.getWxCpConfigStorage();
            if (wxCpConfigStorage == null) {
                throw new BusinessException("获取企微服务失败!");
            }
            String url = String.format(wxCpConfigStorage.getApiUrl(getFollowUserUrl),wxCpConfigStorage.getAccessToken());
            try {
                HttpPost httpPost = new HttpPost(url);
                JsonObject jsonObject = new JsonObject();
                jsonObject.addProperty("msgid", msgId);
                StringEntity entity = new StringEntity(jsonObject.toString(), Consts.UTF_8);
                httpPost.setEntity(entity);

                String resultContent;
                try (CloseableHttpClient httpClient = wxCpService.getRequestHttpClient();
                     CloseableHttpResponse response = httpClient.execute(httpPost)) {
                    resultContent = new BasicResponseHandler().handleResponse(response);
                } finally {
                    httpPost.releaseConnection();
                }
                WxError error = WxError.fromJson(resultContent, WxType.CP);
                if (error.getErrorCode() != 0) {
                    LogUtils.error("取消发送任务失败，原因：{}",error.getErrorMsg());
                    return false;
                }else{
                    return true;
                }
            } catch (IOException e) {
                LogUtils.error("取消发送任务失败，原因：{}",e);
                return false;
            }
        }catch(Exception ex){
            return false;
        }
    }

    private IMsgGroupMassMessageService getBean(){
        return SpringBeanUtil.getBean(MsgGroupMassMessageServiceImpl.class);
    }
}
